生成器函數是JavaScript在ES6中引入的一個新特性,使用'function'語法定義,並通過'yield'來產生一個可迭代的序列。生成器的主要特性在於它們能夠保存其執行狀態,並能夠在多次調用中暫停和恢復。簡單的說,他允許我們創建可以暫停和恢復執行的特殊函數。這種函數在處理複雜的異步操作、迭代大量數據或者需要按需生成數據的場景中特別有用。使得生成器非常適合處理異步編程、迭代大型數據結構等等。
//基本語法
function* generatorFunction() {
yield value1;
yield value2;
// ...
}
例子:
function* countUp() {
yield 1;
yield 2;
yield 3;
}
let generator = countUp();
console.log(generator.next().value); // 輸出:1
console.log(generator.next().value); // 輸出:2
console.log(generator.next().value); // 輸出:3
console.log(generator.next().value); // 輸出:undefined
1.狀態保存 'yield'關鍵字
生成器函數的執行可以在'yield'位置暫停然後返回一個值,並在之後的調用中恢復。這使得它能夠保存內部狀態。
function* fibonacci() {
let [prev, curr] = [0, 1];
while (true) {
[prev, curr] = [curr, prev + curr];
yield curr;
}
}
let fib = fibonacci();
for (let i = 0; i < 10; i++) {
console.log(fib.next().value);
}
// 輸出:1, 2, 3, 5, 8, 13, 21, 34, 55, 89
也可以將執行委托給另一個生成器:
function* gen1() {
yield 'a';
yield 'b';
}
function* gen2() {
yield* gen1();
yield 'c';
}
for (let value of gen2()) {
console.log(value);
}
// 輸出:a, b, c
2.雙向通信 'next()'方法和值的傳遞
生成器函數允許從外部傳入值,使用'next(value)'方法可以傳入一個值,該值會被'yield'表達式的返回值接收。
function* twoWayGenerator() {
let received = yield "First yield";
console.log("Received:", received);
received = yield "Second yield";
console.log("Received:", received);
}
let gen = twoWayGenerator();
console.log(gen.next().value); // 輸出:First yield
console.log(gen.next("Hello").value); // 輸出:Received: Hello,然後輸出:Second yield
console.log(gen.next("World").value); // 輸出:Received: World,然後輸出:undefined
3.迭代器 'for...of'循環
生成器函數可以直接用於'for...of'循環和其他需要可迭代對象的地方。
function* numberGenerator() {
yield 1;
yield 2;
yield 3;
}
for (let num of numberGenerator()) {
console.log(num);
}
// 輸出:1, 2, 3
小筆記:生成器函數自動實現了迭代器協議
生成器函數使用'function'定義,並且在執行時自動返回一個迭代器對象。這意味著可以不需要手動實現'next()'方法和'Symbol.iterator'方法。生成器函數本身就已經符合迭代器協議。